package com.xwj.java8.test;

import com.xwj.java8.utils.SortedUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author xwj
 * @date 2021/4/23 13:17
 * description:Java8 添加了一个新的抽象称为流 Stream，可以以一种声明的方式处理数据。
 * 使用一个流的时候，通常包括三个基本步骤，获取数据源（source）-> 数据转换 -> 执行操作获取结果，每次转换原有 Stream 对象不改变，返回一个新的 Stream 对象.
 * 生成 Stream Source
 */
public class StreamTest1 {
    public static void main(String[] args) {
        //常用的创建流的方式如下，
        //数组
        //可以使用 Arrays.stream()或者 stream.of()
        String[] arr = new String[]{"cat", "dog", "fish"};
        Stream<String> stream = Arrays.stream(arr);
        stream = Stream.of(arr);
        //of()方法内部其实调用了 Arrays.stream()

        //集合
        //可以直接使用 stream()或者使用 parallelStream()方法创建并发流，默认使用的是 ForkJoinPool.commonPool()线程池
        List<String> list = new ArrayList<>();
        list.add("cat");
        list.add("dog");
        list.add("fish");
        stream = list.stream();

        List<Long> aList = new ArrayList<>();
        Stream<Long> parallelStream = aList.parallelStream();

        //操作流
        //流的操作类型分为两种
        //1. Intermediate：一个流可以后面跟随 0 个或多个 intermediate 操作，其目的主要是打开流，然后进行数据过滤、映射等操作，然后返回一个新的流，
        // 交给下一个操作使用，这类操作是惰性化的，就是说，仅仅调用到这类方法，并没有真正开始流的遍历。
        //2. Terminal：一个流只能有一个 terminal 操作，当这个操作执行后，流就被使用“光”了，无法再被操作，termial 操作的执行，才会真正开始流的遍历，
        // 并且会生成一个结果，或者一个副作用（side effect）。

        //常用操作
        //1. map，把 input Stream 的每一个元素映射成 output Stream 的另外一个元素，是 1:1 映射，如果要一对多映射，则需要使用 flatMap
        //转换大写
        List<String> wordList = new ArrayList<>();
        list.add("cat");
        list.add("dog");
        list.add("fish");
        List<String> output = wordList.stream()
                .map(String::toUpperCase)
                .collect(Collectors.toList());
        System.out.println(output);

        //平方数
        List<Integer> nums = Arrays.asList(1, 2, 3, 4);
        List<Integer> squareNums = nums.stream()
                .map(n -> n * n)
                .collect(Collectors.toList());
        System.out.println(squareNums);
        //1. flatMap，把 input Stream 中的层级结构扁平化，就是将最底层元素抽出来放到一起，最终 output 的新 Stream 里面已经没有 List 了，都是直接的数字
        Stream<List<Integer>> inputStream = Stream.of(Collections.singletonList(1),
                Arrays.asList(2, 3),
                Arrays.asList(4, 5, 6));
        Stream<Integer> outputStream = inputStream.flatMap(Collection::stream);
        List<Integer> outputList = outputStream.collect(Collectors.toList());
        System.out.println(outputList);

        //1. filter 对原始 Stream 进行某种过滤，通过过滤的元素被留下来生成一个新 Stream
        //经过“被 2 整除”的 filter，剩下数字为{2, 4, 6}
        Integer[] sixNums = {1, 2, 3, 4, 5, 6};
        Integer[] evens = Stream.of(sixNums)
                .filter(n -> n % 2 == 0)
                .toArray(Integer[]::new);
        System.out.println(evens);

        //1. peek 对每个元素执行操作并返回一个新的 Stream
        List<String> result = Stream.of("one", "two", "three", "four")
                .filter(e -> e.length() > 3)
                .peek(e -> System.out.println("filtered value is " + e))
                .map(String::toUpperCase)
                .peek(e -> System.out.println("Mapped value is " + e))
                .collect(Collectors.toList());
        System.out.println(result);

        //Optional 示例
        //Java8
        String text = null;
        Optional.ofNullable(text).ifPresent(System.out::println);
        if (null != text) {
            System.out.println(text);
        }

        int i = Optional.ofNullable(text).map(String::length).orElse(-1);
        System.out.println("len: " + i);
    }
}
